ImageGear Professional v18.4 > User Guide > Using ImageGear > Images and Documents > Run Ends Image Storage Format > Sample Run Ends Code |
The following is a sample function that decompresses a run ends raster into uncompressed unpacked (1 byte per pixel) format. It's designed to work with the data you would get from IG_runs_row_get().
Copy Code
|
|
---|---|
// runsToUnpacked: Decompresses a run ends raster to unpacked format. // nWidth - width of image in pixels // lpRuns - pointer to input buffer containing run ends data // lpPixels - pointer to output buffer to receive unpacked pixel data void runsToUnpacked(AT_DIMENSION nWidth, LPAT_RUN lpRuns, LPAT_PIXEL lpPixels) { // Starting color is white AT_PIXEL outputPixColor = 1; // Loop through runs AT_INT outputPixPos = 0; while (1) { // Find out when the current run ends AT_RUN runEnd = *lpRuns++; // Fill in pixels for this run while (outputPixPos < runEnd) lpPixels[outputPixPos++] = outputPixColor; // Have we reached the end? if (outputPixPos >= nWidth) break; // Switch colors for next run outputPixColor = !outputPixColor; } } |
The following is a more minimalist view of the same function:
Copy Code
|
|
---|---|
void runsToUnpacked(AT_DIMENSION w, LPAT_RUN lpRuns, LPAT_PIXEL lpPixels) { AT_PIXEL c = 1; AT_INT x = 0; while (1) { AT_RUN r = *lpRuns++; while (x < r) lpPixels[x++] = c; if (x >= w) break; c = !c; } } |
The following is a more complex function that creates a 90-degree rotated copy of an image. It operates entirely on run ends data without ever decompressing the data. Note that this is only sample code. This does not represent how ImageGear works internally. Also, error handling is omitted.
Copy Code
|
|
---|---|
// Returns a 90-degree rotated copy of the source image HIGEAR rotate90(HIGEAR hImageSrc) { HIGEAR hImageDst = NULL; HIGDIBINFO hDIB; AT_INT d[1] = { 1 }; AT_DIMENSION srcWidth, srcHeight, dstWidth, dstHeight; AT_PIXPOS x, y; // Get info about source image IG_image_dimensions_get(hImageSrc, &srcWidth, &srcHeight, NULL); // Create destination image dstWidth = srcHeight; dstHeight = srcWidth; IG_DIB_info_create(&hDIB, dstWidth, dstHeight, IG_COLOR_SPACE_ID_I, 1, d); IG_DIB_palette_alloc(hDIB); IG_image_create(hDIB, &hImageDst); IG_DIB_info_delete(hDIB); AT_RGB rgb = { 255, 255, 255 }; IG_palette_entry_set(hImageDst, &rgb, 1); // Make a list of source raster pointers LPAT_RUN *lpSrcRasters = NULL; lpSrcRasters = (LPAT_RUN *) malloc(sizeof(LPAT_RUN) * srcHeight); // Make a list of current colors for source runs LPAT_BYTE lpSrcRunColors = NULL; lpSrcRunColors = (LPAT_BYTE) malloc(sizeof(AT_BYTE) * srcHeight); // Populate the lists for (y = 0; y < srcHeight; y++) { AT_RUN runCount; IG_runs_row_get(hImageSrc, y, &runCount, &lpSrcRasters[y]); if (*lpSrcRasters[y]) lpSrcRunColors[y] = 1; else { lpSrcRunColors[y] = 0; lpSrcRasters[y]++; } } // Allocate a raster large enough to store worst-case input data LPAT_RUN lpDstRaster = (LPAT_RUN) malloc(sizeof(AT_RUN) * (dstWidth + 4)); // Loop through output rasters for (y = 0; y < dstHeight; y++) { AT_INT nDstRuns = 0; AT_BYTE dstRunColor = 1; AT_INT srcRasterIndex = srcHeight - 1; // If the first source pixel is black, // set us up to start with black in the output raster if (!lpSrcRunColors[srcRasterIndex]) { dstRunColor = 0; lpDstRaster[nDstRuns++] = 0; } // Loop through columns in destination image for (x = 0; x < dstWidth; x++) { // Check the color of the run in the source raster that // corresponds to the current column in the destination raster. // Is it the same color as the run we're currently constructing? if (lpSrcRunColors[srcRasterIndex] != dstRunColor) { // If not, then we need to store the run we've been making // in the destination raster. lpDstRaster[nDstRuns++] = x; // Alternate the current destination run color dstRunColor = !dstRunColor; } // See if it's time to move on to the next source run for // this source raster if (*lpSrcRasters[srcRasterIndex] == y) { lpSrcRasters[srcRasterIndex]++; lpSrcRunColors[srcRasterIndex] = !lpSrcRunColors[srcRasterIndex]; } // Move on to the next source raster (go *up* through the source image) srcRasterIndex--; } // Add the three ending runs to the destination raster lpDstRaster[nDstRuns++] = dstWidth; lpDstRaster[nDstRuns++] = dstWidth; lpDstRaster[nDstRuns++] = dstWidth; // Store the destination raster! IG_runs_row_set(hImageDst, y, nDstRuns, lpDstRaster); } // Clean up free(lpSrcRasters); free(lpSrcRunColors); free(lpDstRaster); return hImageDst; } |